home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
misc
/
digivfo
/
dds.a86
< prev
next >
Wrap
Text File
|
1995-03-23
|
46KB
|
1,498 lines
;--------------------------------------------
; Harris 45102 DDS routines. -
; Dover Research Corporation -
; November 2nd 1993, Feb 19th 1995 -
; All rights reserved -
; -
; Author: James J. Craswell WB0VNE/AAV5TH -
; Part of a commercial product so this code -
; Is NOT Public Domain -
; (612) 492-3913 -
;--------------------------------------------
; BUGS: -
; Display still does not work properly if -
; you operate outside of the 1 MHz range. -
;--------------------------------------------
data segment
org 08000h
io_count dw 0 ; 0 = non-intialized count
io_flag db 0 ; bit 7=1 at end of 5mS wait
msb dw ? ;Storage place for data
lsb dw ? ;Bottom word for data.
msb1 dw ? ;temp location for add/sub.
lsb1 dw ?
msb2 dw ? ;temp location for step hold area.
lsb2 dw ?
msb3 dw ? ;Temp location for comparisons.
lsb3 dw ?
msb4 dw ?
lsb4 dw ?
msb5 dw ?
lsb5 dw ?
;32Bit Divide stuff.
dvmsb dw ? ;Dividend.
dvlsb dw ? ;The number to be divided.
dmsb dw ? ;Divisor.
dlsb dw ?
rmsb dw ? ;Remainder
rlsb dw ?
amsb dw ? ;32Bit answer.
alsb dw ?
msbf1 dw ?
lsbf1 dw ?
msbf2 dw ?
lsbf2 dw ?
msbf3 dw ?
lsbf3 dw ?
msbf4 dw ?
lsbf4 dw ?
msbf5 dw ?
lsbf5 dw ?
msbf6 dw ?
lsbf6 dw ?
msbf7 dw ?
lsbf7 dw ?
msbf8 dw ?
lsbf8 dw ?
msbf9 dw ?
lsbf9 dw ?
msbf10 dw ?
lsbf10 dw ?
msbs dw ? ;Step locations.
lsbs dw ?
mode db ? ;Mode For step up/down program.
;0 = 0.1 / 0.009
;1 = 1 / 0.1
;2 = 10 / 1
;3 = 100 / 10
;4 = 1KHz / 100
;5 = 10KHz / 1KHz
;6 = 100KHz / 10KHz
;7 = 1MHz / 100KHz
;------------------
; VFO START RANGE -
;------------------
;vfomsb equ 2051h ;MSB - TR7A.
;vfolsb equ 0efffh ;LSB - 5.05 to 5.55 MHz
vfomsb equ 2333h ;MSB - KENWOOD TS130.
vfolsb equ 3053h ;LSB - 5.5 MHz to 6.0 MHz
;vfomsb equ 7599h ;msb to set VFO to 140MHz.
;vfolsb equ 7bd2h ;lsb to set VFO to 140MHz.
;--------------------------------------------
; All numbers based on the assumption that...
; 1 = .009313588 HRz steps
;--------------------------------------------
h001 equ 1h ;0.009 Hertz steps.
h01 equ 0ah ;0.1 Hertz steps.
h1 equ 6bh ;1 Hertz steps.
h10 equ 431h ;10 Hertz stepss.
h100 equ 29f1h ;100 Hertz steps.
h1kl equ 0a36ah ;lsb 1KHz steps.
h1km equ 1h ;msb 1KHz steps.
h10kl equ 6224h ;lsb 10KHz steps.
h10km equ 10h ;msb 10KHz steps.
h100kl equ 0d568h ;lsb 100KHz steps.
h100km equ 0a3h ;msb 100KHz steps.
h1ml equ 6516h ;lsb 1Mhz steps.
h1mm equ 666h ;msb 1MHz steps.
esc equ 01h ;Escape scan code
who equ 35h ;? character.
shhome equ 4700h
home equ 4737h
shend equ 4f00h
endkey equ 4f31h
shup equ 4838h ;Shift up arrow.
shdn equ 5032h ;Shift down arrow.
upar equ 4800h ;Up arrow.
dnar equ 5000h ;down arrow.
akey equ 1eh ;a key.
bkey equ 30h ;b key.
ckey equ 2eh ;c key.
dkey equ 20h ;d key.
fkey equ 21h ;f key.
pkey equ 19h ;p key.
rkey equ 13h ;r key.
skey equ 1fh ;s key.
pgdn equ 51h ;Page Down key.
pgup equ 49h ;Page up key.
pluskey equ 4eh ;Plus key.
minkey equ 4ah ;Minus key.
f1key equ 3bh ;Function keys
f2key equ 3ch
f3key equ 3dh
f4key equ 3eh
f5key equ 3fh
f6key equ 40h
f7key equ 41h
f8key equ 42h
f9key equ 43h
f10key equ 44h
lcnt equ 32 ;How many bits to shift.
;ioport equ 3bch ;Compaq portable port (also LPT1:)
ioport equ 278h ;Address of PCOSITIVE printer port.
;ioport equ 378h ;Address of the other printer port
idle equ 0b4h ;Sets the machine to the idle state.
xfer equ 0fbh ;and mask to turn off 4 bit - 32b clk to dds.
dat1 equ 2 ;Set the data bit off.
clk equ 1 ;Clock a data bit in.
stepm equ 0h ;msb for step.
stepl equ 431h ;1 = 0.009HRz step.
val db ? ;One byte storage.
data ends
;-----------------------------------
code segment
Start: call cls ;clear screen
mov dx,OFFSET msg ;Load banner msg
call print ;Print the advert to the screen.
mov dx,OFFSET msg0
call print
mov (lsb1),h1kl
mov (msb1),h1km
mov (lsb2),h10kl
mov (msb2),h10km
mov (mode),5
mov msbf1,vfomsb ;Initialize all memory channels to zero.
mov lsbf1,vfolsb ;New version will load these from a disk file.
mov msbf2,msbf1
mov lsbf2,lsbf1
mov msbf3,msbf1
mov lsbf3,lsbf1
mov msbf4,msbf1
mov lsbf4,lsbf1
mov msbf5,msbf1
mov lsbf5,lsbf1
mov msbf6,msbf1
mov lsbf6,lsbf1
mov msbf7,msbf1
mov lsbf7,lsbf1
mov msbf8,msbf1
mov lsbf8,lsbf1
mov msbf9,msbf1
mov lsbf9,lsbf1
mov msbf10,msbf1
mov lsbf10,lsbf1
call idleit ;Start DDS in idle mode.
init: mov msb,vfomsb ;Store start freq MSB.
mov lsb,vfolsb ;Store start freq lsb.
call loadit
call loadit ;Set DDS to zero freq.
; mov cx,lcnt ;Load length of data to shift (32 bits).
; mov si,msb ;Load msb
; mov di,lsb ;Load lsb
; call wrtdat ;Write data bit.
; call xferit ;Signal transfer done.
; call idleit
keylp: call disfrq
call keyin ;Read a keystroke.
key3: cmp ax,upar ;Up freq 1x?
jnz key4
call up1x
jmp keylp
key4: cmp ax,dnar ;Down freq 1x?
jnz key5
call dn1x
jmp keylp
key5: cmp ax,shup ;Bump freq up 10x?
jnz key6
call up10x
jmp keylp
key6: cmp ax,shdn ;Bump freq down 10x?
jnz key7
call dn10x
jmp keylp
key7: cmp ah,pkey ;Panadapter bandscanner key?
jnz key8
call sweep
jmp keylp
key8: cmp ah,who ;?Copyright help info?
jnz key9
call copyr
jmp keylp
key9: cmp ah,skey ;(S)ave a freq in a memory (F) key.
jnz key10
call savem ;Save memory.
mov dx,OFFSET msg11
call print
jmp keylp
key10: cmp ah,esc ;Is this an ESC key?
jnz key11
jmp endit ;It is so end this program now.
key11: cmp ah,rkey ;Reset VFO to zero?
jnz key12
jmp init ;restart program.
key12: cmp ah,pluskey ;Bump frequency steps up?
jnz key13
call bumpup
jmp keylp
key13: cmp ah,minkey ;Bump frequency steps down?
jnz key14
call bumpdn
jmp keylp
key14: cmp ah,dkey ;Direct frequency entry?
jnz key15 ;Jump if not.
call direct
jmp keylp
key15: cmp ah,f1key ;Play back a memory key?
jnz key16 ;Such as F1?
mov msb,msbf1
mov lsb,lsbf1
call loadit
call loadit
jmp keylp
key16: cmp ah,f2key ;Play back F2?
jnz key17
mov msb,msbf2
mov lsb,lsbf2
call loadit
call loadit
jmp keylp
key17: cmp ah,f3key ;Play back F3?
jnz key18
mov msb,msbf3
mov lsb,lsbf3
call loadit
call loadit
jmp keylp
key18: cmp ah,f4key ;Play back F4?
jnz key19
mov msb,msbf4
mov lsb,lsbf4
call loadit
call loadit
jmp keylp
key19: cmp ah,f5key ;Play back F5?
jnz key20
mov msb,msbf5
mov lsb,lsbf5
call loadit
call loadit
jmp keylp
key20: cmp ah,f6key ;Play back F6?
jnz key21
mov msb,msbf6
mov lsb,lsbf6
call loadit
call loadit
jmp keylp
key21: cmp ah,f7key ;Play back F7?
jnz key22
mov msb,msbf7
mov lsb,lsbf7
call loadit
call loadit
jmp keylp
key22: cmp ah,f8key ;Play back F8?
jnz key23
mov msb,msbf8
mov lsb,lsbf8
call loadit
call loadit
jmp keylp
key23: cmp ah,f9key ;Play back F9?
jnz key24
mov msb,msbf9
mov lsb,lsbf9
call loadit
call loadit
jmp keylp
key24: cmp ah,f10key ;Play back F10?
jnz key25
mov msb,msbf10
mov lsb,lsbf10
call loadit
call loadit
jmp keylp
key25: cmp ah,bkey ;Band / Step setting for panadaptor?
jnz key100
call disfrq
jmp keylp
key100: call beep
jmp keylp
;--------------------------------
; Subroutines
;--------------------------------
;---------------------------------------------
; END: Return to PCDOS.
;---------------------------------------------
endit: mov dx,OFFSET msg1 ;Load banner msg
call print ;Print the advert to the screen.
mov ax,04c00 ;EXIT
int 33
;-----------------------------------------
; Step up (or down) 1x.
;-----------------------------------------
up1x: call add32 ;Add it up.
call loadit ;Signal transfer done.
call loadit
ret
dn1x: call sub32 ;Subtract it.
call loadit ;Signal transfer done.
call loadit
ret
;-----------------------------------------
; Step up (or down) 10x.
; lsb1/msb1=1x values.
; lsb2/msb2=10x values.
; lsb3/msb3 scratch locations.
;-----------------------------------------
up10x: mov (lsb3),(lsb1) ;Save 1x values in xsb3.
mov (msb3),(msb1)
mov (lsb1),(lsb2) ;Load 10x lsb steps.
mov (msb1),(msb2) ;Load 10x msb steps.
call add32 ;Add it up.
call loadit ;Load the new freq into the DDS.
call loadit
mov (lsb1),(lsb3) ;Restore 1x vlaues.
mov (msb1),(msb3)
ret ;Return.
dn10x: mov (lsb3),(lsb1) ;Save 1x values in xsb3.
mov (msb3),(msb1)
mov (lsb1),(lsb2) ;Load 10x lsb steps.
mov (msb1),(msb2) ;Load 10x msb steps.
call sub32 ;Subtract from the current freq.
call loadit ;Load the new freq into the DDS.
call loadit
mov (lsb1),(lsb3) ;Restore 1x vlaues.
mov (msb1),(msb3)
ret ;Return.
;-----------------------------------------
; Save current freq to a memory key.
;-----------------------------------------
savem: mov dx,OFFSET savemsg
call print
call keyin ;Read the keyboard.
f1: cmp ah,f1key
jnz f2
mov msbf1,msb
mov lsbf1,lsb
ret
f2: cmp ah,f2key
jnz f3
mov msbf2,msb
mov lsbf2,lsb
ret
f3: cmp ah,f3key
jnz f4
mov msbf3,msb
mov lsbf3,lsb
ret
f4: cmp ah,f4key
jnz f5
mov msbf4,msb
mov lsbf4,lsb
ret
f5: cmp ah,f5key
jnz f6
mov msbf5,msb
mov lsbf5,lsb
ret
f6: cmp ah,f6key
jnz f7
mov msbf6,msb
mov lsbf6,lsb
ret
f7: cmp ah,f7key
jnz f8
mov msbf7,msb
mov lsbf7,lsb
ret
f8: cmp ah,f8key
jnz f9
mov msbf8,msb
mov lsbf8,lsb
ret
f9: cmp ah,f9key
jnz f10
mov msbf9,msb
mov lsbf9,lsb
ret
f10: cmp ah,f10key
jnz bad
mov msbf10,msb
mov lsbf10,lsb
ret
bad: call beep
mov dx,OFFSET badkey
call print
jmp savem
;-----------------------------------------
; Direct keyboard entry of the freq.
;-----------------------------------------
direct: mov dx,OFFSET msg12b
call print ;Clear the line.
mov dx,OFFSET msg12
call print ;Print the freq: xx. line
mov cx,0
mov msb3,msb1 ;Save original values.
mov lsb3,lsb1
mov msb1,h100km ;Get 100 Khz digit into add/sub reg.
mov lsb1,h100kl
mov msb,vfomsb ;Clear VFO to zero.
mov lsb,vfolsb
call getdig ;Get first digit.
cmp cx,0
jz .nk1
.m100: call add32
loop .m100
.nk1: call loadit ;Load the new frequency
call loadit
mov cx,0 ;Restore original step.
mov msb1,h10km
mov lsb1,h10kl
call getdig ;Get a digit.
cmp cx,0 ;Check for zero digit.
jz .nk2 ;Zero so don't add anything.
.m10: call add32
loop .m10
.nk2: call loadit
call loadit
mov cx,0
mov cx,0 ;Restore original step.
mov msb1,h1km
mov lsb1,h1kl
call getdig ;Get a digit.
cmp cx,0 ;Check for zero digit.
jz .nk3 ;Zero so don't add anything.
.m1: call add32
loop .m1
.nk3: call loadit
call loadit
mov dx,OFFSET mdot
call print
mov cx,0 ;Restore original step.
mov msb1,0 ;No msb to add.
mov lsb1,h100
call getdig ;Get a digit.
cmp cx,0 ;Check for zero digit.
jz .nk4 ;Zero so don't add anything.
.m01: call add32
loop .m01
.nk4: call loadit
call loadit
mov cx,0
mov cx,0 ;Restore original step.
mov msb1,0 ;No msb to add.
mov lsb1,h10
call getdig ;Get a digit.
cmp cx,0 ;Check for zero digit.
jz .nk5 ;Zero so don't add anything.
.m001: call add32
loop .m001
.nk5: call loadit
call loadit
mov cx,0 ;Restore original step.
mov msb1,0 ;No msb to add.
mov lsb1,h1
call getdig ;Get a digit.
cmp cx,0 ;Check for zero digit.
jz .nk6 ;Zero so don't add anything.
.m0001: call add32
loop .m0001
.nk6: mov dx,OFFSET mdot
call print
call loadit
call loadit
mov cx,0 ;Restore original step.
mov msb1,0 ;No msb to add.
mov lsb1,h01
call getdig ;Get a digit.
cmp cx,0 ;Check for zero digit.
jz .nk7 ;Zero so don't add anything.
.m00001:call add32
loop .m00001
.nk7: call loadit
call loadit
mov dx,OFFSET crlf
call print
mov msb1,msb3 ;Restore up down values.
mov lsb1,lsb3
ret ;Return to main routine.
getdig: call keyin
cmp al,30h ;0
jnz .k1
mov cx,0
mov dx,OFFSET mn0
call print
ret
.k1: cmp al,31h
jnz .k2
mov cx,1
mov dx,OFFSET mn1
call print
ret
.k2: cmp al,32h ;2
jnz .k3
mov cx,2
mov dx,OFFSET mn2
call print
ret
.k3: cmp al,33h ;3
jnz .k4
mov cx,3
mov dx,OFFSET mn3
call print
ret
.k4: cmp al,34h ;4
jnz .k5
mov cx,4
mov dx,OFFSET mn4
call print
ret
.k5: cmp al,35h ;5
jnz .k6
mov cx,5
mov dx,OFFSET mn5
call print
ret
.k6: cmp al,36h ;6
jnz .k7
mov cx,6
mov dx,OFFSET mn6
call print
ret
.k7: cmp al,37h ;7
jnz .k8
mov cx,7
mov dx,OFFSET mn7
call print
ret
.k8: cmp al,38h ;8
jnz .k9
mov cx,8
mov dx,OFFSET mn8
call print
ret
.k9: cmp al,39h ;9
jnz .kbad
mov cx,9
mov dx,OFFSET mn9
call print
ret
.kbad: call beep
jmp getdig
;-----------------------------------------
; Copyright message.
;-----------------------------------------
copyr: call cls ;Clear the screen.
mov dx,OFFSET cmsg
call print
mov dx,OFFSET msg0
call print
ret
;-----------------------------------------
; Sweep a range.
;-----------------------------------------
sweep: mov dx,OFFSET msg10
call print
jmp keylp ;Forget it we arent done with panadaptor yet.
mov ax,stepl ;Load our step frequency.
mov bx,stepm
mov (lsbs),ax ;Move step freq into ax.
mov (msbs),bx ;Don't forget the msb!
mov lsb1,ax ;Put into...
mov msb1,bx ;Add subtract registers.
itnow: call add32 ;Add it up.
call loadit ;send new freq to the dds chip.
call loadit
mov ah,11h ;Check for a keystroke.
int 16h
jz itnow ;No key so keep on sweeping.
jmp endit
jmp keylp ;Got a key so process it.
bumpup: mov al,(mode) ;Read current mode.
cmp al,7 ;Compare against max allowed value.
jz enuf ;Thats close enough!
inc al ;Else raise value.
mov (mode),al ;Save it for next time around.
cmp al,1 ;Is it 1 / 0.1?
jz m1
cmp al,2 ;Is it 10 / 1?
jz m2
cmp al,3 ;Is it 100 / 10?
jz m3
cmp al,4 ;Is it 1KHz / 100?
jz m4
cmp al,5 ;Is it 10KHz / 1KHz?
jz m5
cmp al,6 ;Is it 100KHz / 10KHz?
jz m6
cmp al,7 ;Is it 1MHz / 100KHz?
jz m7
jmp keylp
m0: jmp mode0
m1: jmp mode1
m2: jmp mode2
m3: jmp mode3
m4: jmp mode4
m5: jmp mode5
m6: jmp mode6
m7: jmp mode7
;-----------------------------------------
;Value already at max or minumum value.
;-----------------------------------------
enuf: call beep ;Warn operator.
jmp keylp
bumpdn: mov al,(mode) ;Read current mode.
cmp al,0 ;Compare against minimum allowed value.
jz enuf ;Thats close enough!
dec al ;Else lower value.
mov (mode),al ;Save it for next time around.
cmp al,0 ;Is it 0.1 / 0.009?
jz m0
cmp al,1 ;Is it 1 / 0.1?
jz m1
cmp al,2 ;Is it 10 / 1?
jz m2
cmp al,3 ;Is it 100 / 10?
jz m3
cmp al,4 ;Is it 1KHz / 100?
jz m4
cmp al,5 ;Is it 10KHz / 1KHz?
jz m5
cmp al,6 ;Is it 100KHz / 10KHz?
jz m6
jmp keylp ;NOTE IT SHOULD BE IMPOSSABLE TO REACH THIS LOC.
mode0: mov dx,OFFSET msg2
call print
mov (lsb1),h001
mov (msb1),0
mov (lsb2),h01
mov (msb2),0
ret
mode1: mov dx,OFFSET msg3
call print
mov (lsb1),h01
mov (msb1),0
mov (lsb2),h1
mov (msb2),0
ret
mode2: mov dx,OFFSET msg4
call print
mov (lsb1),h1
mov (msb1),0
mov (lsb2),h10
mov (msb2),0
ret
mode3: mov dx,OFFSET msg5
call print
mov (lsb1),h10
mov (msb1),0
mov (lsb2),h100
mov (msb2),0
ret
mode4: mov dx,OFFSET msg6
call print
mov (lsb1),h100
mov (msb1),0
mov (lsb2),h1kl
mov (msb2),h1km
ret
mode5: mov dx,OFFSET msg7
call print
mov (lsb1),h1kl
mov (msb1),h1km
mov (lsb2),h10kl
mov (msb2),h10km
ret
mode6: mov dx,OFFSET msg8
call print
mov (lsb1),h10kl
mov (msb1),h10km
mov (lsb2),h100kl
mov (msb2),h100km
ret
mode7: mov dx,OFFSET msg9
call print
mov (lsb1),h100kl
mov (msb1),h100km
mov (lsb2),h1ml
mov (msb2),h1mm
ret
;------------------------------------------
; PANADAPTOR SET
;------------------------------------------
panset: call beep
ret
;------------------------------------------
; Loads the new frequency into the DDS.
;------------------------------------------
loadit:
mov cx,lcnt ;Load length of data to shift (32 bits).
mov si,msb ;Load msb
mov di,lsb ;Load lsb
call wrtdat ;Write data bit.
call xferit ;Signal transfer done.
; push dx
; mov dx,OFFSET msgli
; call print
; pop dx
ret
;------------------------------------------
; WRITE DATA:
; MSB/LSB contain the 32 bit long word
; that shall be written to the I/O port.
;------------------------------------------
wrtdat: mov ax,idle ;Assume data bit is zero.
add di,di ;This routine will pop off the top bit in a
adc si,si ;32 bit long word.
jc da1 ;Data is equal to one.
back: call outit ;Write data to the I/O port.
or al,clk ;Turn on the clock bit.
call outit ;Clk in the valid data bit.
mov al,idle ;set data reg to idle.
call outit ;Idle the DDS chip.
dec cx ;sub 1 the count reg.
jnz wrtdat ;Loop til all 32 bits are sent out.
ret ;All 32 bits sent out so return.
da1: or al,dat1 ;Set data bit on.
jmp back ;Go back to routine.
;---------------------------------------------
; IDLE:
; This routine sets the control lines to idle.
;---------------------------------------------
idleit: mov dx,ioport ;Load the printer ports address.
mov al,idle ;Set al to idle.
call outit ;This sets the dds chip to idle.
ret ;And return.
;---------------------------------------------
; TRANSFER:
; This routine signals the DDS that a 32 bit
; command has been sent.
;---------------------------------------------
xferit: mov dx,ioport ;Load the port address.
mov ax,idle ;Load al with idle.
and al,xfer ;Now Or in the xfer bit.
call outit ;DDS accepts 32bit data on rising edge of xfer.
mov al,idle ;Reload Idle.
call outit ;Write it to I/O port.
ret ;And return.
;---------------------------------------------
; I/O PORT ROUTINE.
;---------------------------------------------
outit: out dx,al
; call iodelay ;iodelay is a time hog forget this unless your
;machine won't work right.
ret
;---------------------------------------------
; 32 Bit comparison.
; NOT FINISHED YET SO DON'T CALL THIS!!!
; If msb3/lsb3 is larger then carry=1 on return.
;---------------------------------------------
comp32: push ax ;Save so we can use as scratch.
push bx ;Dito.
mov ax,(lsb) ;Load current value.
mov bx,(lsb3) ;Get msb number to compare.
sub ax,bx ;Subtract low order portion.
mov ax,(msb) ;Load current value.
mov bx,(msb3) ;Get lsb number to compare.
sbb ax,bx ;Compare it.
pop bx ;Restore scratch.
pop ax ;Restore scratch.
ret
;----------------------------------
; 32Bit addition routine:
; msb lsb 32 bit number and answer.
; msb1/lsb1 32 bit number to add.
;----------------------------------
add32: push ax ;Save so we can use as scratch.
push bx ;Dito.
mov ax,(lsb) ;Load current value.
mov bx,(lsb1) ;Get number to add.
add ax,bx ;add values.
mov (lsb),ax ;Save new lsb.
mov ax,(msb) ;Load current msb.
mov bx,(msb1) ;Get number to add.
adc ax,bx ;add values + carry bit.
mov (msb),ax ;Save new msb.
pop bx ;Restore scratch.
pop ax ;Restore scratch.
ret ;Return to caller.
;-----------------------------------------
; 32Bit subtraction routine:
; msb/lsb 32 Bit number to be sub from.
; msb1/lsb 32 Bit number to subtract with.
;-----------------------------------------
sub32: push ax ;Save so we can use as scratch.
push bx ;Dito.
mov ax,(lsb) ;Load current value.
mov bx,(lsb1) ;Get number to subtract.
sub ax,bx ;subtract values.
mov (lsb),ax ;Save new lsb.
mov ax,(msb) ;Load current msb.
mov bx,(msb1) ;Get number to add.
sbb ax,bx ;sub values with borrow bit.
mov (msb),ax ;Save new msb.
pop bx ;Restore scratch register.
pop ax ;Dito.
ret ;Return to caller.
;--------------------------------
; 32Bit Multiplication routine:
; msb/lsb Number to multiply.
; msb1/lsb1 Times its multiplied.
;--------------------------------
mul32: push ax ;Save so we can use as scratch.
push bx ;Dito.
push cx
pop cx
pop bx ;Restore scratch registers.
pop ax
ret ;Return to caller.
ret ;Return to caller.
;--------------------------------
; All rights reserved. -
; Dover Research Corporation -
; 1979,1994 -
;--------------------------------
; 32 Bit division routine -
;--------------------------------
; Answer -
; __________ -
; Divisor) Dividend -
; -
;--------------------------------
;--------------------------------
; Divide two 32Bit integers. -
; dvmsb/dvlsb Dividend. -
; dmsb/dlsb Divider. -
; -
; Answer in amsb/alsb. -
; Remainder in rmsb/rlsb. -
;--------------------------------
div32: push ax ;Save scratch registers.
push bx
push dx
push si
;-------------------------
; Test for 32/16 Bit math?
;-------------------------
mov ax,(dmsb) ;Read upper word.
or ax,ax ;test upper word for zero.
jnz IsLong ;Jump if 32 bit value.
;------------------------------
; Divide 32bit by 16 bit value.
;------------------------------
mov cx,(dlsb) ;Call this routine when we can.
mov ax,(dvmsb) ;It saves lots of stupid looping.
xor dx,dx
div cx
mov bx,ax
mov ax,(dvlsb)
div cx
mov (amsb),bx
mov (alsb),ax
;------------------------------
; Calculate 32/16Bit remainder
; If not needed jump to byebye.
;------------------------------
mov ax,(dlsb) ;Load divisor lsb (no msb in 16bit math)
mov bx,(alsb) ;Load lsb Divisor.
mul bx ;AX * BX = DX:AX
mov (rmsb),dx ;Save 1st half of remainder msb.
mov (rlsb),ax ;Save 1st half of remainder lsb.
mov ax,(dlsb) ;Reload divisor lsb.
mov bx,(amsb) ;Load msb Divisor.
mul bx ;AX * BX = DX:AX
add (rmsb),ax ;Add 2nd half of remainder.
;---------------------------------
; Subtract to determine remainder.
;---------------------------------
mov ax,(dvlsb) ;Dividend.
mov bx,(rlsb) ;Total.
sub ax,bx
mov (rlsb),ax ;Store remainder lsb.
mov ax,(dvmsb) ;Answer msb.
mov bx,(rmsb)
sbb ax,bx ;Sub values with borrow bit.
mov (rmsb),ax ;Save remainder msb.
jmp byebye
;-----------------------------
; Divide 32bit by 32bit value.
;-----------------------------
IsLong: mov cx,ax
mov bx,(dlsb)
mov dx,(dvmsb)
mov ax,(dvlsb)
;-------------------------
; Division by powers of 2.
;-------------------------
ShiftLoop:
shr cx,1
rcr bx,1
shr dx,1
rcr ax,1
or cx,cx
jnz ShiftLoop
div bx ;Answer in ax.
mov si,ax
mul (dmsb)
xchg ax,cx
mov ax,(dlsb)
mul si
add dx,cx
jc IsCarry
cmp dx,(dvmsb)
jnbe IsCarry
jc IsNull
cmp ax,(dvlsb)
jbe IsNull
IsCarry:dec si
IsNull: xor dx,dx
xchg ax,si
mov (amsb),0
mov (alsb),ax
;------------------------------
; Calculate 32/32Bit remainder
; If not needed jump to byebye.
;------------------------------
mov ax,(dlsb) ;Load Divisor lsb.
mov bx,(alsb) ;Load lsb answer.
mul bx ;AX * BX = DX:AX
mov (rmsb),dx ;Save 1st half of remainder msb.
mov (rlsb),ax ;Save 1st half of remainder lsb.
mov ax,(dmsb)
mov bx,(alsb) ;Answer in 32Bit div is always just lsb.
mul bx ;AX * BX = DX:AX
add (rmsb),ax ;Add 2nd half of remainder.
;---------------------------------
; Subtract to determine remainder.
;---------------------------------
mov ax,(dvlsb)
mov bx,(rlsb)
sub ax,bx
mov (rlsb),ax ;Store remainder lsb.
mov ax,(dvmsb)
mov bx,(rmsb)
sbb ax,bx ;Sub values with borrow bit.
mov (rmsb),ax ;Save remainder msb.
byebye: pop si
pop dx
pop bx
pop ax
ret
;---------------------------------------------
; DISPLAY CURRENT FREQUENCY.
; Step = lsb1/msb1
; VFO = lsb/msb
; 5.05MHz = vfomsb/vfolsb (in binary DDS talk)
;---------------------------------------------
grok db 'display freq'
disfrq: push ax
push bx
push cx
push dx
mov dx,OFFSET msg12b
call print ;Clear status line and home cursor.
mov dx,OFFSET msg14
call print
mov (msb5),(msb1) ;Save step freq.
mov (lsb5),(lsb1)
mov (msb4),(msb) ;Save current VFO frequency.
mov (lsb4),(lsb)
mov cx,0 ;Clear cx
mov (msb1),vfomsb ;load 5.05 MHz freq.
mov (lsb1),vfolsb
call sub32 ;msb/lsb = freq (not freq + 5.05 MC)
mov (dvmsb),(msb) ;Load current VFO freq + 5.05 to Dividend.
mov (dvlsb),(lsb)
mov (dmsb),h100km ;Load divisor with 100Khz value.
mov (dlsb),h100kl
call div32 ;How many 100Khzs do we have?
mov cx,(alsb)
call pnum ;Show first number on display.
mov (dvmsb),(rmsb) ;use remainder for next calculation.
mov (dvlsb),(rlsb)
mov (dmsb),h10km ;Get 10Khz value.
mov (dlsb),h10kl
call div32 ;How many 10Khzs do we have?
mov cx,(alsb)
call pnum ;Show second number on display.
mov (msb),(rmsb) ;use remainder for next calculation.
mov (lsb),(rlsb)
mov (dvmsb),(rmsb) ;use remainder for next calculation.
mov (dvlsb),(rlsb)
mov (dmsb),h1km ;Load 1 Khz value.
mov (dlsb),h1kl
call div32 ;How many 1Khzs do we have?
mov cx,(alsb)
call pnum ;Show third number.
mov (msb),(rmsb) ;use remainder for next calculation.
mov (lsb),(rlsb)
mov dx,OFFSET mdot ;Load period.
call print ;and print it now.
mov (dvmsb),(rmsb) ;use remainder for next calculation.
mov (dvlsb),(rlsb)
mov (dmsb),0 ;Msb is zero for these values.
mov (dlsb),h100 ;load 100 Hz value.
call div32 ;how many 100 hzs do we have?
mov cx,(alsb)
call pnum ;Print fourth number.
mov (msb),(rmsb) ;use remainder for next calculation.
mov (lsb),(rlsb)
mov (dvmsb),(rmsb) ;use remainder for next calculation.
mov (dvlsb),(rlsb)
mov (dmsb),0
mov (dlsb),h10 ;load 10 Hz value.
call div32 ;How many 10 Hzs do we have?
mov cx,(alsb)
call pnum ;print fifth number.
mov (msb),(rmsb) ;use remainder for next calculation.
mov (lsb),(rlsb)
mov (dvmsb),(rmsb) ;use remainder for next calculation.
mov (dvlsb),(rlsb)
mov (dmsb),0
mov (dlsb),h1 ;load 1 hz value.
call div32 ;how many 1 hzs do we have?
mov cx,(alsb)
call pnum ;print sixth number.
mov (msb),(rmsb) ;use remainder for next calculation.
mov (lsb),(rlsb)
mov dx,OFFSET mdot ;Load period...
call print ;and print it.
mov (dvmsb),(rmsb) ;use remainder for next calculation.
mov (dvlsb),(rlsb)
mov (dlsb),h01 ;load 0.1 hz value.
call div32 ;How many 0.1 hzs do we have left?
mov cx,(alsb)
call pnum ;Print em!
mov (msb),(rmsb) ;use remainder for next calculation.
mov (lsb),(rlsb)
mov dx,OFFSET crlf ;home cursor. msg15
call print
;----------------------------------------------------
; Done printing frequency so restore all the goodies.
;----------------------------------------------------
mov (msb1),(msb5) ;Restore step freq.
mov (lsb1),(lsb5)
mov (msb),(msb4) ;Restore current VFO frequency.
mov (lsb),(lsb4)
pop dx ;Restore work registers.
pop cx
pop bx
pop ax
ret ;Return to caller.
;------------------------------
; PRINT A NUMBER (Binary-ASCII)
; My crude way to take a
; binary number and print it.
;------------------------------
pnum: nop
nop
nop
cmp cl,10 ;Weird roll off test.
jne norm ;0,1,2,3,4,5,6,7,8,10.
dec cl ;It IS weird so make it normal.
norm: add cl,30h ;Convert to ascii.
mov dl,cl
mov ah,06h
int 21h ;Direct console output.
mov cx,0
ret
;---------------------------------------------
; KEYBOARD I/O
;---------------------------------------------
keyin: mov ah,10h
int 16h
ret ;Return to caller.
;---------------------------------------------
; PRINT:
; DX Contains the offset to the $ terminated
; text string to be printed to the screen.
;---------------------------------------------
print: push ax
mov ah,9
int 21h
pop ax
ret ;Return to caller.
;---------------------------------------------
; CLEAR THE SCREEN
;---------------------------------------------
cls: push ax
push bx
push cx
push dx
mov ah,6 ;Scroll up funtion
mov al,0 ;code to blank screen.
mov ch,0 ;upper left row.
mov cl,0 ;Upper left column.
mov dh,50 ;Lower right row.
mov dl,79 ;Lower right column
mov bh,7 ;Blank line attribute.
int 10h ;Call video rom.
pop dx
pop cx
pop bx
pop ax
ret
;---------------------------------------------
; BEEP: SOUNDS THE ERROR TONE ON THE SPEAKER.
;---------------------------------------------
beep: push ax
push bx
push cx
push dx
cli ;no interrupts
mov si,2 ;do hole thing twice
agin1: mov bp,20 ;we want 20 cycles of sound
mov al,10110110xb ;must address channel 2
out 43h,al ;mode 3 - send it
mov bx,100 ;start frequency very high
agin2: mov ax,bx ;place in (ax)
out 42h,al ;send LSB
mov al,ah ;move MSB into (al)
out 42h,al ;send it to port
in al,61h ;get value from speaker port
or al,00000011xb ;ORing turns speaker on
out 61h,al ;send it
mov cx,30000 ;our delay count
looperq:loop looperq ;do nothing loop so we can hear sound
add bx,50 ;lower frequency a bit for next pass
in al,61h ;get value from port
and al,11111100xb ;ANDing turns speaker off
out 61h,al ;send it
dec bp ;decrement cycle count
jnz agin2 ;if not = 0 do again
dec si ;else decrement repeat count
jnz agin1 ;if not = 0 do hole thing again
sti ;else turn interrupts back on
pop dx
pop cx
pop bx
pop ax
ret
;───────────────────────────────────────────────────────────────
; I/O DELAY
; Delay to ensure successive I/O operations to the same
; device are not too fast on a fast CPU. First time
; iodelay is called, a 5 mS delay occurs to calibrate
; the delay loop.
;
; Called with: nothing
;
; Returns: delay of 1 to 16 uS
;
; Regs used: none (flags altered)
iodelay:push cx ;Save count register.
mov cx, cs:[io_count] ;Read our count...
jcxz io_init ;Is it set?
io_delay_loop:
loop io_delay_loop ; 13 cycles per loop on a 386
pop cx
ret
; first time run, so determine initialization value and save
io_init:
push ax ;Save registers.
push bx
push dx
push es
mov ax, cs
mov es, ax
mov ax, 8300h ; set wait interval
mov cx, 0
mov dx, 5000 ; delay 5 mS, util wait flag
mov bx, offset io_flag ; is set
int 15h ; start 5 mS delay
jc io_failed_15 ; unimplemented or in progress
; the RTC timer has begun, and will set bit 7 of the wait flag when
; 5 mS elapses. Meanwhile, the software loop counts down slowly for
; slow systems, and fast for fast systems. The loop is 30 cycles
; on a 386 CPU. Other CPUs will vary slightly from this.
dec cx ; cx = FFFFh
io_delay_loop2:
test cs:[io_flag],45 ; flag set after 5 mS
jnz io_5ms_done ; jump if 5 ms complete
jmp short $+2
loop io_delay_loop2
mov ax, 100 ; gets here if > 400 Mhz CPU,
jmp io_exit ; so use really large number
; cx = countdown from FFFF
io_5ms_done:
mov ax, 0FFFFh
sub ax, cx ; get number of times looped
mov bx, 1500 ; adjustment factor
xor dx, dx ; dx zeroed for divde
div bx ; ax= dx:ax/cx
cmp ax, 0
je io_1_delay ; set at least 1 delay
jmp io_set ; ax = delay value
io_failed_15:
or ah, ah ; was int 15 supported or busy?
jz io_exit ; jump if busy, try again later
; only slow machines fail int 15h
io_1_delay:
mov ax, 1 ; mininum delay period
io_set:
mov cs:[io_count], ax ; load delay value
io_exit:
pop es
pop dx
pop bx
pop ax
pop cx
ret
crlf: db 13
db "$"
cmsg: db "* * * * * * * * * * * * * * *",13,10
db "* DOVER DIGITAL VFO *",13,10
db "* COPYRIGHT DOVER RESEARCH *",13,10
db "* All rights reserved *",13,10
db "* (612)492-3913 *",13,10
db "* by Jay Craswell *",13,10
db "* WB0VNE / AAV5TH *",13,10
db "* NOT PUBLIC DOMAIN *",13,10
db "* * * * * * * * * * * * * * *",13,10,10
db "$"
savemsg:db "Press an F Key to store this frequency. ",13
db "$"
msg: db "* * * * * * * * * * * * * * *",13,10
db "* DOVER DIGITAL VFO *",13,10
db "* <<<<<<<< Rev 1.4 >>>>>>>> *",13,10
db "* 5.5 MHz to 6.0 MHz Version*",13,10
db "* * * * * * * * * * * * * * *",13,10
db "$"
msg0: db "(d)irect keyboard entry.",13,10
db "(p)anadaptor (with option).",13,10
db "(r)eset VFO to zero.",13,10
db "(s)ave a freq to a memory key.",13,10
db "(b)and edges & Panadaptor step.",13,10
db "(?) About DigiVFO.",13,10
db "(+) Raise VFO steps.",13,10
db "(-) Lower VFO steps.",13,10
db "Up Arrow (shiftable) freq up.",13,10
db "Dn Arrow (shiftable) freq dn.",13,10
db "ESC quits to DOS",13,10,10
db "----------------------------------------"
db "----------------------------------------",13,10
db "$"
msg1: db "Program ends ",13
db "$"
msg2: db " 0.009 / 0.1 Hertz steps",13
db "$"
msg3: db " 0.1 / 1 Hertz steps ",13
db "$"
msg4: db " 1 / 10 Herts steps ",13
db "$"
msg5: db " 10 / 100 Hertz steps ",13
db "$"
msg6: db " 100Hertz / 1KHz steps ",13
db "$"
msg7: db " 1 / 10KHz steps ",13
db "$"
msg8: db " 10KHz / 100KHz steps ",13
db "$"
msg9: db " 100KHz / 1Mc steps ",13
db "$"
msg10: db "Sorry not in this version ",13
db "$"
msg11: db "Memory stored.. ",13
db "$"
msg12: db "Enter "
db "xx."
db "$"
msg12b: db " ",13
db "$"
msg14: db "Freq: xx."
db "$"
msg15 db " |",13
mdot: db "."
db "$"
badkey: db "Not a valid choice. ",13
db "$"
msgli: db "Loading it! ",13
db "$"
mn0: db "0"
db "$"
mn1: db "1"
db "$"
mn2: db "2"
db "$"
mn3: db "3"
db "$"
mn4: db "4"
db "$"
mn5: db "5"
db "$"
mn6: db "6"
db "$"
mn7: db "7"
db "$"
mn8: db "8"
db "$"
mn9: db "9"
db "$"
code ends